package com.gitee.wsl.mathematics.geometry.d2.rect.ext

import com.gitee.wsl.mathematics.coordinate.d2.Coordinate2
import com.gitee.wsl.mathematics.geometry.d2.rect.RectangleShape2d
import com.gitee.wsl.mathematics.vector.vec2.Vector2


/** Merges this rectangle with the other rectangle. The rectangle should not have negative width or negative height.
 * @param rect the other rectangle
 * @return this rectangle for chaining
 */
fun<N:Number,V: Coordinate2<N, V>,R: RectangleShape2d<N, V, R>> R.merge(rect: R): R {
    val minX = min(x, rect.x)
    val maxX = max(x + width, rect.x + rect.width)
    //x = minX
    //width = maxX - minX
    val minY = min(y, rect.y)
    val maxY = max(y + height, rect.y + rect.height)
    //y = minY
    //height = maxY - minY
    return create(minX,minY,maxX,maxY)
}

/** Merges this rectangle with a point (x, y).
 * The rectangle should not have negative width or negative height. */
fun<N:Number,V: Coordinate2<N, V>,R: RectangleShape2d<N, V, R>> R.merge(x: N, y: N): R {
    val minX = min(this.x, x)
    val maxX = max(this.x + width, x)
    //this.x = minX
    //width = maxX - minX
    val minY = min(this.y, y)
    val maxY = max(this.y + height, y)
    //this.y = minY
    //height = maxY - minY
    return create(minX,minY,maxX,maxY)
}

/** Merges this rectangle with a point. The rectangle should not have negative width or negative height. */
fun<N:Number,V: Coordinate2<N, V>,R: RectangleShape2d<N, V, R>> R.merge(point: Vector2<N,*>) = merge(point.x, point.y)

/** Merges this rectangle with a list of points. The rectangle should not have negative width or negative height. */
fun<N:Number,V: Coordinate2<N, V>,R: RectangleShape2d<N, V, R>> R.merge(points: List<Vector2<N,*>>): R {
    var minX = x
    var maxX = x + width
    var minY = y
    var maxY = y + height
    for (i in points.indices) {
        val v = points[i]
        minX = min(minX, v.x)
        maxX = max(maxX, v.x)
        minY = min(minY, v.y)
        maxY = max(maxY, v.y)
    }
    //x = minX
    //width = maxX - minX
    //y = minY
    //height = maxY - minY
    return create(minX,minY,maxX,maxY)
}